// /*
//  * _______________#########_______________________ 
//  * ______________############_____________________ 
//  * ______________#############____________________ 
//  * _____________##__###########___________________ 
//  * ____________###__######_#####__________________ 
//  * ____________###_#######___####_________________ 
//  * ___________###__##########_####________________ 
//  * __________####__###########_####_______________ 
//  * ________#####___###########__#####_____________ 
//  * _______######___###_########___#####___________ 
//  * _______#####___###___########___######_________ 
//  * ______######___###__###########___######_______ 
//  * _____######___####_##############__######______ 
//  * ____#######__#####################_#######_____ 
//  * ____#######__##############################____ 
//  * ___#######__######_#################_#######___ 
//  * ___#######__######_######_#########___######___ 
//  * ___#######____##__######___######_____######___ 
//  * ___#######________######____#####_____#####____ 
//  * ____######________#####_____#####_____####_____ 
//  * _____#####________####______#####_____###______ 
//  * ______#####______;###________###______#________ 
//  * ________##_______####________####______________ 
//  * 
//  * @Author: ipk518 18163976442@163.com
//  * @Date: 2024-08-14 19:42:24
//  * @LastEditors: ipk518 18163976442@163.com
//  * @LastEditTime: 2024-08-14 19:42:25
//  * @FilePath: /qsfp/i2c-driver.c
//  * @Description: 
//  * ************佛祖保佑************
//  * Copyright (c) 2024 by etws@quyujiang, All Rights Reserved. 
//  */

// /*
//  * temperature bus driver
//  *
//  * Copyright (C) 2014 CGT Corp.
//  *
//  * This program is free software; you can redistribute it and/or modify
//  * it under the terms of the GNU General Public License as published by
//  * the Free Software Foundation; version 2 of the License.
//  *
//  * This program is distributed in the hope that it will be useful,
//  * but WITHOUT ANY WARRANTY; without even the implied warranty of
//  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  * GNU General Public License for more details.
//  *
//  * You should have received a copy of the GNU General Public License
//  * along with this program; if not, write to the Free Software
//  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
//  *
//  */
 
// #define DEBUG
 
// #include <linux/kernel.h>
// #include <linux/module.h>
// #include <linux/slab.h>
// #include <linux/i2c.h>
// #include <linux/mutex.h>
// #include <linux/delay.h>
 
// #include <linux/serial_core.h>
 
// /* Each client has this additional data */
// #define USER_EEPROM_SIZE	0xFFFF48
// #define USER_XFER_MAX_COUNT	0x8
 
// /* Addresses to scan */
// static const unsigned short temperature_i2c[] = { 0x3, I2C_CLIENT_END };
 
// static unsigned read_timeout = 25;
// module_param(read_timeout, uint, 0);
// MODULE_PARM_DESC(read_timeout, "Time (in ms) to try reads (default 25)");
 
// static unsigned write_timeout = 25;
// module_param(write_timeout, uint, 0);
// MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)");
 
// struct temperature_data {
// 	struct mutex	lock;
// 	u8	*data;
// };
 
// static ssize_t temperature_read_data( struct i2c_client *client,
// 	char *buf, unsigned offset, size_t count)
// {
// 	struct i2c_msg msg[2];
// 	u8 msgbuf[4];
// 	unsigned long timeout, transfer_time;
// 	int status;
 
// 	memset(msg, 0, sizeof(msg));
 
// 	msgbuf[0] = (u8)(offset & 0xff);
 
// 	msg[0].addr = 0x50;//client->addr;
// 	msg[0].buf = msgbuf;
// 	msg[0].len = 1;
 
// 	msg[1].addr = 0x50;//client->addr;
// 	msg[1].flags = I2C_M_RD;
// 	msg[1].buf = buf;
// 	msg[1].len = count;
 
// 	/*
// 	 * Reads fail if the previous write didn't complete yet. We may
// 	 * loop a few times until this one succeeds, waiting at least
// 	 * long enough for one entire page write to work.
// 	 */
// 	timeout = jiffies + msecs_to_jiffies(read_timeout);
// 	do {
// 		transfer_time = jiffies;
 
// 		status = i2c_transfer(client->adapter, msg, 2);
 
// 		if (status == 2)
// 			status = count;
 
// 		dev_dbg(&client->dev, "read %ld@0x%lx --> %d (%ld)\n",
// 				count, (unsigned long)offset, status, jiffies);
 
// 		if (status == count)
// 			return count;
 
// 		/* REVISIT: at HZ=100, this is sloooow */
// 		msleep(1);
// 	} while (time_before(transfer_time, timeout));
 
// 	return -ETIMEDOUT;
 
//  }
 
 
// static ssize_t temperature_read(struct file *filp, struct kobject *kobj,
// 			    struct bin_attribute *bin_attr,
// 			    char *buf, loff_t offset, size_t count)
// {
// 	struct i2c_client *client = kobj_to_i2c_client(kobj);
// 	struct temperature_data *data = i2c_get_clientdata(client);
 
// 	ssize_t retval = 0;
 
// 	if (offset > USER_EEPROM_SIZE)
// 		return 0;
 
// 	if (offset + count > USER_EEPROM_SIZE)
// 		count = USER_EEPROM_SIZE - offset;
 
// 	mutex_lock(&data->lock);
 
// 	dev_dbg(&client->dev, "cps226 start read %ld@0x%lx ..\n", count, (unsigned long)offset);
 
// 	while (count > 0) {
// 		ssize_t	status = count>USER_XFER_MAX_COUNT?USER_XFER_MAX_COUNT:count;
// 		status = temperature_read_data(client, buf, offset, status);
// 		if (status <= 0) {
// 			if (retval == 0)
// 				retval = status;
// 			break;
// 		}
// 		buf += status;
// 		offset += status;
// 		count -= status;
// 		retval += status;
// 	}
 
// 	dev_dbg(&client->dev, "cps226 end read %ld@0x%lx  !\n", retval, (unsigned long)offset);
 
// 	mutex_unlock(&data->lock);
 
// 	return retval;
 
//  }
 
// static ssize_t temperature_write_config(
// 	struct i2c_client *client,
// 	struct temperature_data *data,
// 	char *buf, unsigned offset, size_t count)
// {
// 	struct i2c_msg msg[1];
// 	u8 *msgbuf;
// 	unsigned long timeout, transfer_time;
// 	int status;
 
// 	memset(msg, 0, sizeof(msg));
 
// 	msgbuf = data->data;
 
// //	msgbuf[0] = (u8)((offset >> 18) & 0x3f);
// //	msgbuf[1] = (u8)((offset >> 10) & 0xff);
// //	msgbuf[2] = (u8)((offset >>  2) & 0xff);
 
	
 
// 	msgbuf[0] = (u8)(offset& 0xff);
// 	memcpy(msgbuf+1, buf, count);
// 	msg[0].addr = 0x50;//client->addr;
// 	msg[0].buf = msgbuf;
// 	msg[0].len = 1 + count;
 
 
// 	/*
// 	 * Reads fail if the previous write didn't complete yet. We may
// 	 * loop a few times until this one succeeds, waiting at least
// 	 * long enough for one entire page write to work.
// 	 */
// 	timeout = jiffies + msecs_to_jiffies(write_timeout);
// 	do {
// 		transfer_time = jiffies;
 
// 		status = i2c_transfer(client->adapter, msg, 1);
 
// 		if (status == 1)
// 			status = count;
 
// 		dev_dbg(&client->dev, "write %ld@0x%lx --> %d (%ld)\n",
// 				count, (unsigned long)offset, status, jiffies);
 
// 		if (status == count)
// 			return count;
 
// 		/* REVISIT: at HZ=100, this is sloooow */
// 		msleep(1);
// 	} while (time_before(transfer_time, timeout));
 
// 	return -ETIMEDOUT;
//  }
 
// static ssize_t temperature_write(struct file *filp, struct kobject *kobj,
// 			    struct bin_attribute *bin_attr,
// 			    char *buf, loff_t offset, size_t count)
// {
// 	struct i2c_client *client = kobj_to_i2c_client(kobj);
// 	struct temperature_data *data = i2c_get_clientdata(client);
 
// 	ssize_t retval = 0;
 
// 	if (offset > USER_EEPROM_SIZE)
// 		return 0;
 
// 	if (offset + count > USER_EEPROM_SIZE)
// 		count = USER_EEPROM_SIZE - offset;
 
// 	mutex_lock(&data->lock);
 
// 	dev_dbg(&client->dev, "temperature start write %ld@0x%lx ..\n", count, (unsigned long)offset);
 
// 	while (count > 0) {
// 		ssize_t	status = count>USER_XFER_MAX_COUNT?USER_XFER_MAX_COUNT:count;
// 		status = temperature_write_config(client, data, buf, offset, status);
// 		if (status <= 0) {
// 			if (retval == 0)
// 				retval = status;
// 			break;
// 		}
// 		buf += status;
// 		offset += status;
// 		count -= status;
// 		retval += status;
// 	}
 
// 	dev_dbg(&client->dev, "temperature end write %ld@0x%lx  !\n", retval, (unsigned long)offset);
 
// 	mutex_unlock(&data->lock);
 
// 	return retval;
 
//  }
 
// static struct bin_attribute user_temperature_attr = {
// 	.attr = {
// 		.name = "temperature",
// 		.mode = (S_IRUSR | S_IWUSR),
// 	},
// 	.size = USER_EEPROM_SIZE,
// 	.read = temperature_read,
// 	.write = temperature_write,
// };
 
// /* Return 0 if detection is successful, -ENODEV otherwise */
// static int temperature_detect(struct i2c_client *client, struct i2c_board_info *info)
// {
// 	struct i2c_adapter *adapter = client->adapter;
 
// 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
// 		dev_dbg(&client->dev, "temperature detect error for BYTE access !\n");
// 		return -ENODEV;
// 	}
 
// 	strlcpy(info->type, "temperature", I2C_NAME_SIZE);
 
// 	return 0;
//  }
 
// static int temperature_probe(struct i2c_client *client,
// 			 const struct i2c_device_id *id)
// {
// 	struct i2c_adapter *adapter = client->adapter;
// 	struct temperature_data *data;
// 	int err ;
 
// 	dev_notice(&client->dev, "temperature driver\n" );
 
// 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
// 		dev_err(&client->dev, "temperature data driver:  BYTE DATA not supported! \n" );
// 		return -ENODEV;
// 	}
 
// 	if (!(data = kzalloc(sizeof(struct  temperature_data), GFP_KERNEL))) {
// 		dev_err(&client->dev, "temperature data driver:  Memory alloc error ! \n" );
// 		return -ENOMEM;
// 	}
 
// 	/* alloc buffer */
// 	data->data = devm_kzalloc(&client->dev, USER_XFER_MAX_COUNT + 8, GFP_KERNEL);
// 	if (!data->data) {
// 		dev_err(&client->dev, "temperature data driver:  Memory alloc error ! \n" );
// 		err = -ENOMEM;
// 		goto exit_kfree;
// 	}
 
// 	/* Init real i2c_client */
// 	i2c_set_clientdata(client, data);
// 	mutex_init(&data->lock);
 
// 	err = sysfs_create_bin_file(&client->dev.kobj, &user_temperature_attr);
// 	if (err) {
// 		dev_err(&client->dev, "temperature data driver:  sysfs create error ! \n" );
// 		goto exit_kfree;
// 	}
 
// 	return 0;
 
// exit_kfree:
// 	if(data->data)
// 		kfree(data->data);
// 	kfree(data);
// 	return err;
//  }
 
// static int temperature_remove(struct i2c_client *client)
// {
// 	struct temperature_data *data = i2c_get_clientdata(client);
 
// 	sysfs_remove_bin_file(&client->dev.kobj, &user_temperature_attr);
// 	if(data->data)
// 		kfree(data->data);
// 	kfree(data);
 
// 	return 0;
//  }
 
// static const struct i2c_device_id temperature_id[] = {
// 	{ "temperature", 0 },
// 	{ }
// };
// MODULE_DEVICE_TABLE(i2c, temperature_id);
 
// static struct i2c_driver temperature_driver = {
// 	.driver = {
// 		.name	= "temperature",
// 	},
// 	.probe		= temperature_probe,
// 	.remove		= temperature_remove,
// 	.id_table	= temperature_id,
 
// 	.class		= I2C_CLASS_SPD,
// 	.detect		= temperature_detect,
// 	.address_list	= temperature_i2c,
// };
 
// module_i2c_driver(temperature_driver);
 
// MODULE_AUTHOR("RobinLee");
// MODULE_DESCRIPTION("temperature driver");
// MODULE_LICENSE("GPL");